/**
 * 
 */
package gopi.labs.database;

import gopi.labs.Connector.NameValue;
import gopi.labs.exceptions.InValidIdentifier;
import gopi.labs.exceptions.InvalidDataRecord;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 * @author GS4
 * 
 */
public abstract class DataModel extends Database {

	private String cloudSpace;
	private List<Columns> columns;

	public class Columns {
		String name;
		String dataType;
		String dataLength;

		public Columns(String name, String dataType, String dataLength) {
			this.name = name.toUpperCase();
			this.dataType = dataType.toUpperCase();
			this.dataLength = dataLength;
		}
		public Columns(String name, String dataType) {
			this.name = name.toUpperCase();
			this.dataType = dataType.toUpperCase();
			this.dataLength = null;
		}
		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name.toUpperCase();
		}

		public String getDataType() {
			return dataType;
		}

		public void setDataType(String dataType) {
			this.dataType = dataType.toUpperCase();
		}

		public String getDataLength() {
			return dataLength;
		}

		public void setDataLength(String dataLength) {
			this.dataLength = dataLength;
		}

	}

	public DataModel(String name) {
		super(name);
		this.columns = new ArrayList<Columns>();
	}

	public abstract void create() throws SQLException, InvalidDataRecord;

	public abstract void alter() throws SQLException, InvalidDataRecord;

	public abstract void drop() throws SQLException;

	@Override
	public void validate() throws InValidIdentifier, SQLException {
		super.validate();

		if (this.getCloudSpace() == null || this.getCloudSpace().equalsIgnoreCase(""))
			throw new InValidIdentifier(
					"CloudSpace for a datamodel cannot be null");
		if (this.getCloudSpace() != null && !this.checkCloudExists(this.getCloudSpace()))
			throw new InValidIdentifier("CloudSpace " + this.getCloudSpace()
					+ " does not exists");

		boolean valid = true;

		if (this.columns == null || this.columns.size() == 0) {
			throw new InValidIdentifier("DataModel " + this.getCloudSpace() + "."
					+ this.getName() + " has no columns defined");
		}
		StringBuffer str = new StringBuffer();
		for (int i = 0; i < this.columns.size(); i++) {
			if (this.columns.get(i).getName() == null
					|| this.columns.get(i).getName().equalsIgnoreCase("")) {
				valid = false;
				str.append("Column name cannot be null index = " + i + "\n");
			}
			if (this.columns.get(i).getDataType() == null) {
				valid = false;
				str.append("Column " + this.columns.get(i).getName()
						+ " has no datatype defined ...");
			} else if (this.columns.get(i).getDataType()
					.equalsIgnoreCase("VARCHAR")
					&& (this.columns.get(i).getDataLength() == null || this.columns
							.get(i).getDataLength().equalsIgnoreCase(""))) {
				valid = false;
				str.append("Column " + this.columns.get(i).getName()
						+ " has no datatype defined ...");
			}
		}
		
		if (!valid)
			 throw new InValidIdentifier(str.toString());
	}

	

	public List<NameValue> getAttributeDetails() throws SQLException,
			InvalidDataRecord {
		List<NameValue> dataModelDetails = new ArrayList<NameValue>();
		Statement stmt = this.connection.createStatement();
		if (!checkDataModelExists(this.getName(), this.getCloudSpace()))
			throw new InvalidDataRecord("DataModel name " + this.getName()
					+ " does not exist");

		ResultSet rs = stmt
				.executeQuery("select * from metadata.data_model where name = '"
						+ this.getName()
						+ "' and cloud_name = '"
						+ this.getCloudSpace() + "'");

		while (rs.next()) {
			for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
				dataModelDetails.add(new NameValue(rs.getMetaData()
						.getColumnLabel(i), rs.getString(i)));
			}
		}
		rs = stmt
				.executeQuery("select * from metadata.data_model_attributes where name = '"
						+ this.getName()
						+ "' and cloud_name = '"
						+ this.getCloudSpace() + "'");

		while (rs.next()) {
			dataModelDetails.add(new NameValue(rs.getString("attribute"), rs
					.getString("value")));
		}
		return dataModelDetails;

	}

	@Override
	public void insertUpdateAttributes(List<NameValue> attributes)
			throws SQLException {
		Statement stmt = this.connection.createStatement();
		for (int i = 0; i < attributes.size(); i++) {
			ResultSet rs = stmt
					.executeQuery("select count(*) from metadata.data_model_attributes"
							+ " where name = '"
							+ this.getName()
							+ "' and cloud_name = '"
							+ this.getCloudSpace()
							+ "' and attribute='"
							+ attributes.get(i).getName().toString() + "'");
			rs.next();
			if (rs.getInt(1) == 0) {
				stmt.execute("insert into metadata.data_model_attributes"
						+ " (cloud_name, name, attribute, value) values "
						+ "('" + this.getCloudSpace() + "','" + this.getName()
						+ "','" + attributes.get(i).getName() + "','"
						+ attributes.get(i).getValue() + "')");
			} else {
				stmt.execute("update metadata.data_model_attributes set value =  '"
						+ attributes.get(i).getValue()
						+ "' where cloud_name = '"
						+ this.getCloudSpace()
						+ "' and name = '"
						+ this.getName()
						+ "' and attribute = '"
						+ attributes.get(i).getName()
						+ "'");
			}
			rs.close();
		}
	}

	public void addColumns(String name, String dataType, String dataLength) {
		this.columns.add(new Columns(name, dataType, dataLength));
	}

	public void addColumns(String name, String dataType) {
		this.columns.add(new Columns(name, dataType));
	}
	public List<Columns> getColumns() {
		return this.columns;
	}

	public String getCloudSpace() {
		return cloudSpace;
	}

	public void setCloudSpace(String cloudSpace) {
		this.cloudSpace = cloudSpace.toUpperCase();
	}

}
